import path from 'path';
import { IJsonTable } from '../interfaces/IJsonTable';
import { TableConfig, QueryCondition, OperationResult, IndexConfig, IEncryptor, ISerializer } from '../types';
import { FileSystem } from '../utils/fileSystem';
import { QueryUtils } from '../utils/queryUtils';
import { ICache } from '../interfaces/ICache';
import { LRUCache } from './Cache';
import { JsonSerializer } from '../serializers';
import { Backup } from '../utils/backup';

/**
 * 数据表类
 */
export class JsonTable implements IJsonTable {
    /** 表配置 */
    private readonly config: TableConfig;

    /** 表数据文件路径 */
    private readonly tablePath: string;

    /** 索引文件路径 */
    private readonly indexesPath: string;

    /** 加密器 */
    private readonly encryptor?: IEncryptor;

    /** 序列化器 */
    private readonly serializer: ISerializer;

    /** 缓存实例 */
    private readonly cache?: ICache<string, any>;

    /** 表数据 */
    private data: any[] = [];

    /**
     * 索引映射
     * Map<索引名称, Map<索引值, Set<数据位置>>>
     */
    private indexes: Map<string, Map<string, Set<number>>> = new Map();

    /** 是否已加载数据 */
    private loaded: boolean = false;

    /** 是否正在保存 */
    private saving: boolean = false;

    /** 挂起的保存操作 */
    private pendingSave: boolean = false;

    /** 上次保存时间 */
    private lastSaveTime: number = 0;

    /** 最小保存间隔（毫秒） */
    private static readonly MIN_SAVE_INTERVAL = 1000;

    /** 最大重试次数 */
    private static readonly MAX_RETRIES = 3;

    /**
     * 构造函数
     * @param config 表配置
     * @param dbPath 数据库路径
     * @param encryptor 加密器（可选）
     */
    constructor(config: TableConfig, dbPath: string, encryptor?: IEncryptor) {
        if (!config.cache || config.cache.enabled == undefined) {
            config.cache = {
                enabled: true,
                ttl: 24 * 60 * 60 * 1000
            }
        }
        this.config = config;

        // 初始化加密器
        this.encryptor = config.encryptor || encryptor;

        // 初始化序列化器
        this.serializer = config.serializer || new JsonSerializer();

        // 设置文件路径，支持自定义扩展名
        const extension = config.extension || this.serializer.getDefaultExtension();
        this.tablePath = path.join(dbPath, 'tables', `${config.name}${extension}`);
        this.indexesPath = path.join(dbPath, 'tables', `${config.name}.index.json`);

        // 初始化缓存
        if (config.cache?.enabled) {
            this.cache = new LRUCache(
                config.cache.maxItems || 1000,
                config.cache.ttl
            );
        }
    }

    /**
     * 初始化表数据
     */
    private async initialize(): Promise<void> {
        if (this.loaded) return;

        try {
            // 读取表数据
            if (await FileSystem.exists(this.tablePath)) {
                const content = await FileSystem.readFile(this.tablePath, this.encryptor);
                try {
                    this.data = this.serializer.deserialize(content);
                } catch (error) {
                    // 如果反序列化失败，尝试从最新备份恢复
                    const backupPath = await Backup.getLatestBackup(this.tablePath);
                    if (backupPath) {
                        await Backup.restore(this.tablePath, backupPath, this.encryptor);
                        const backupContent = await FileSystem.readFile(this.tablePath, this.encryptor);
                        this.data = this.serializer.deserialize(backupContent);
                    } else {
                        throw error;
                    }
                }
            }

            // 读取索引数据
            if (await FileSystem.exists(this.indexesPath)) {
                const indexData = await FileSystem.readJson<Record<string, Record<string, number[]>>>(
                    this.indexesPath,
                    this.encryptor
                );
                // 转换索引数据为内存格式
                Object.entries(indexData).forEach(([indexName, indexMap]) => {
                    const index = new Map<string, Set<number>>();
                    Object.entries(indexMap).forEach(([key, positions]) => {
                        index.set(key, new Set(positions));
                    });
                    this.indexes.set(indexName, index);
                });
            }

            // 验证并重建索引
            await this.validateIndexes();
        } catch (error) {
            throw new Error(`Failed to initialize table: ${(error as Error).message}`);
        }

        this.loaded = true;
    }

    /**
     * 验证并重建索引
     */
    private async validateIndexes(): Promise<void> {
        // 清空所有索引
        this.indexes.clear();

        // 重建索引
        for (const indexConfig of this.config.indexes || []) {
            const index = new Map<string, Set<number>>();
            this.indexes.set(indexConfig.name, index);

            // 遍历所有数据重建索引
            this.data.forEach((item, position) => {
                const indexValue = this.getIndexValue(item, indexConfig.fields);
                if (indexValue !== undefined) {
                    const positions = index.get(indexValue) || new Set();
                    positions.add(position);
                    index.set(indexValue, positions);
                }
            });

            // 验证唯一索引
            if (indexConfig.unique) {
                for (const [value, positions] of index.entries()) {
                    if (positions.size > 1) {
                        throw new Error(
                            `Unique index violation: ${indexConfig.name} has duplicate value: ${value}`
                        );
                    }
                }
            }
        }

        // 保存索引
        await this.saveIndexes();
    }

    /**
     * 保存表数据
     */
    private async saveData(): Promise<void> {
        const now = Date.now();
        if (this.saving) {
            this.pendingSave = true;
            return;
        }

        // 检查保存间隔
        if (now - this.lastSaveTime < JsonTable.MIN_SAVE_INTERVAL) {
            this.pendingSave = true;
            setTimeout(() => this.processPendingSave(), JsonTable.MIN_SAVE_INTERVAL);
            return;
        }

        this.saving = true;
        this.pendingSave = false;
        this.lastSaveTime = now;

        try {
            // 创建备份
            await Backup.create(this.tablePath, this.encryptor, this.serializer);

            // 保存数据
            const content = this.serializer.serialize(this.data);
            await FileSystem.writeFile(this.tablePath, content, this.encryptor);
        } catch (error) {
            throw new Error(`Failed to save table data: ${(error as Error).message}`);
        } finally {
            this.saving = false;

            // 如果有挂起的保存请求，继续处理
            if (this.pendingSave) {
                setTimeout(() => this.processPendingSave(), 0);
            }
        }
    }

    /**
     * 处理挂起的保存请求
     */
    private async processPendingSave(): Promise<void> {
        if (this.pendingSave && !this.saving) {
            await this.saveData();
        }
    }

    /**
     * 保存索引数据
     */
    private async saveIndexes(): Promise<void> {
        try {
            // 转换索引数据为存储格式
            const indexData: Record<string, Record<string, number[]>> = {};
            for (const [indexName, indexMap] of this.indexes.entries()) {
                indexData[indexName] = {};
                for (const [key, positions] of indexMap.entries()) {
                    indexData[indexName][key] = Array.from(positions);
                }
            }

            // 创建备份
            await Backup.create(this.indexesPath, this.encryptor);

            // 保存索引
            await FileSystem.writeJson(this.indexesPath, indexData, this.encryptor);
        } catch (error) {
            throw new Error(`Failed to save indexes: ${(error as Error).message}`);
        }
    }

    /**
     * 获取索引值
     * @param item 数据项
     * @param fields 字段列表
     */
    private getIndexValue(item: any, fields: string[]): string | undefined {
        try {
            const values = fields.map(field => {
                const value = QueryUtils.getFieldValue(item, field);
                return value === undefined ? '' : String(value);
            });
            return values.join('|');
        } catch {
            return undefined;
        }
    }

    /**
     * 生成缓存键
     * @param conditions 查询条件
     */
    private generateCacheKey(conditions?: QueryCondition[]): string {
        if (!conditions || conditions.length === 0) {
            return '_all_';
        }
        return JSON.stringify(conditions.sort((a, b) =>
            a.field.localeCompare(b.field) ||
            a.operator.localeCompare(b.operator)
        ));
    }

    /**
     * 从缓存中获取数据
     * @param conditions 查询条件
     */
    private getCachedResult(conditions?: QueryCondition[]): any[] | undefined {
        if (!this.cache) return undefined;
        const key = this.generateCacheKey(conditions);
        return this.cache.get(key);
    }

    /**
     * 将结果存入缓存
     * @param conditions 查询条件
     * @param results 结果数据
     */
    private cacheResults(conditions: QueryCondition[] | undefined, results: any[]): void {
        if (!this.cache) return;
        const key = this.generateCacheKey(conditions);
        this.cache.set(key, results);
    }

    /**
     * 清除缓存
     */
    private clearCache(): void {
        if (this.cache) {
            this.cache.clear();
        }
    }

    /**
     * 查询数据
     * @param conditions 查询条件
     */
    async find(conditions?: QueryCondition[]): Promise<OperationResult> {
        try {
            // 尝试从缓存获取
            const cachedResults = this.getCachedResult(conditions);
            if (cachedResults !== undefined) {
                return {
                    success: true,
                    data: cachedResults
                };
            }

            await this.initialize();

            const results = [];
            const matchedPositions = this.findMatchingPositions(conditions);

            for (const position of matchedPositions) {
                results.push(this.data[position]);
            }

            // 缓存结果
            this.cacheResults(conditions, results);

            return {
                success: true,
                data: results
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 插入数据
     * @param data 数据对象
     */
    async insert(data: any): Promise<OperationResult> {
        try {
            await this.initialize();

            // 添加数据
            const position = this.data.length;
            this.data.push(data);

            // 更新索引
            await this.updateIndexes(data, position);

            // 保存数据
            await this.saveData();
            await this.saveIndexes();

            // 清除缓存
            this.clearCache();

            return {
                success: true,
                data: { id: position }
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 更新数据
     * @param conditions 查询条件
     * @param updateData 更新数据
     */
    async update(conditions: QueryCondition[], updateData: any): Promise<OperationResult> {
        try {
            await this.initialize();

            let updatedCount = 0;
            const matchedPositions = this.findMatchingPositions(conditions);

            for (const position of matchedPositions) {
                // 移除旧索引
                await this.removeFromIndexes(this.data[position], position);

                // 更新数据
                Object.entries(updateData).forEach(([key, value]) => {
                    QueryUtils.setValueByPath(this.data[position], key, value);
                });

                // 添加新索引
                await this.updateIndexes(this.data[position], position);
                updatedCount++;
            }

            if (updatedCount > 0) {
                await this.saveData();
                await this.saveIndexes();
                // 清除缓存
                this.clearCache();
            }

            return {
                success: true,
                affectedRows: updatedCount
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 删除数据
     * @param conditions 查询条件
     */
    async delete(conditions: QueryCondition[]): Promise<OperationResult> {
        try {
            await this.initialize();

            const matchedPositions = Array.from(this.findMatchingPositions(conditions));
            if (matchedPositions.length === 0) {
                return {
                    success: true,
                    affectedRows: 0
                };
            }

            // 从大到小排序，以便从后向前删除
            matchedPositions.sort((a, b) => b - a);

            // 删除数据和索引
            for (const position of matchedPositions) {
                await this.removeFromIndexes(this.data[position], position);
                this.data.splice(position, 1);
            }

            await this.saveData();
            await this.saveIndexes();

            // 清除缓存
            this.clearCache();

            return {
                success: true,
                affectedRows: matchedPositions.length
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 查找匹配的数据位置
     * @param conditions 查询条件
     */
    private findMatchingPositions(conditions?: QueryCondition[]): Set<number> {
        if (!conditions || conditions.length === 0) {
            return new Set(this.data.keys());
        }

        // 尝试使用索引
        const indexedPositions = this.findPositionsByIndex(conditions);
        if (indexedPositions) {
            return indexedPositions;
        }

        // 全表扫描
        return new Set(
            this.data
                .map((item, index) => ({ item, index }))
                .filter(({ item }) => QueryUtils.matchConditions(item, conditions))
                .map(({ index }) => index)
        );
    }

    /**
     * 使用索引查找数据位置
     * @param conditions 查询条件
     */
    private findPositionsByIndex(conditions: QueryCondition[]): Set<number> | null {
        // 查找可用的索引
        for (const [indexName, index] of this.indexes) {
            const indexFields = indexName.split('_');
            const matchingCondition = conditions.find(condition =>
                indexFields.includes(condition.field) &&
                condition.operator === 'eq'
            );

            if (matchingCondition) {
                const key = this.generateIndexKey({ [matchingCondition.field]: matchingCondition.value }, [matchingCondition.field]);
                return index.get(key) || new Set();
            }
        }

        return null;
    }

    /**
     * 生成索引键
     * @param data 数据对象
     * @param fields 字段数组
     */
    private generateIndexKey(data: any, fields: string[]): string {
        return fields
            .map(field => QueryUtils.getValueByPath(data, field))
            .map(value => String(value))
            .join('|');
    }

    /**
     * 更新索引
     * @param data 数据对象
     * @param position 位置
     */
    private async updateIndexes(data: any, position: number): Promise<void> {
        for (const [indexName, index] of this.indexes) {
            const fields = indexName.split('_');
            const key = this.generateIndexKey(data, fields);

            if (!index.has(key)) {
                index.set(key, new Set());
            }
            index.get(key)!.add(position);
        }
    }

    /**
     * 从索引中移除数据
     * @param data 数据对象
     * @param position 位置
     */
    private async removeFromIndexes(data: any, position: number): Promise<void> {
        for (const [indexName, index] of this.indexes) {
            const fields = indexName.split('_');
            const key = this.generateIndexKey(data, fields);

            const positions = index.get(key);
            if (positions) {
                positions.delete(position);
                if (positions.size === 0) {
                    index.delete(key);
                }
            }
        }
    }

    /**
     * 获取表配置
     */
    getConfig(): TableConfig {
        return { ...this.config };
    }

    /**
     * 批量插入数据
     * @param dataArray 数据对象数组
     */
    async insertMany(dataArray: any[]): Promise<OperationResult> {
        try {
            await this.initialize();

            const startPosition = this.data.length;

            // 添加数据
            this.data.push(...dataArray);

            // 更新索引
            for (let i = 0; i < dataArray.length; i++) {
                await this.updateIndexes(dataArray[i], startPosition + i);
            }

            // 保存数据
            await this.saveData();
            await this.saveIndexes();

            // 清除缓存
            this.clearCache();

            return {
                success: true,
                data: {
                    startId: startPosition,
                    count: dataArray.length
                }
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 查询单条数据
     * @param conditions 查询条件
     */
    async findOne(conditions: QueryCondition[]): Promise<OperationResult> {
        try {
            await this.initialize();

            const matchedPositions = this.findMatchingPositions(conditions);
            const position = matchedPositions.values().next().value;

            if (position === undefined) {
                return {
                    success: true,
                    data: null
                };
            }

            return {
                success: true,
                data: this.data[position]
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 创建索引
     * @param field 字段名或字段名数组
     * @param unique 是否唯一索引
     */
    async createIndex(field: string | string[], unique: boolean = false): Promise<OperationResult> {
        try {
            await this.initialize();

            const fields = Array.isArray(field) ? field : [field];
            const indexName = fields.join('_');

            if (this.indexes.has(indexName)) {
                return {
                    success: false,
                    error: `Index ${indexName} already exists`
                };
            }

            const indexConfig: IndexConfig = {
                name: indexName,
                fields,
                unique
            };

            // 创建索引
            const index = new Map<string, Set<number>>();
            this.data.forEach((item, position) => {
                const key = this.generateIndexKey(item, fields);
                if (!index.has(key)) {
                    index.set(key, new Set());
                }
                index.get(key)!.add(position);
            });

            this.indexes.set(indexName, index);
            await this.saveIndexes();

            return {
                success: true,
                data: indexConfig
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }

    /**
     * 删除索引
     * @param indexName 索引名称
     */
    async dropIndex(indexName: string): Promise<OperationResult> {
        try {
            await this.initialize();

            if (!this.indexes.has(indexName)) {
                return {
                    success: false,
                    error: `Index ${indexName} does not exist`
                };
            }

            this.indexes.delete(indexName);
            await this.saveIndexes();

            return {
                success: true
            };
        } catch (error) {
            return {
                success: false,
                error: (error as Error).message
            };
        }
    }
}
